home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / sendlib.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  35KB  |  1,533 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "rfc2047.h"
  21. #include "send.h"
  22. #include "mx.h"
  23. #include "mime.h"
  24. #include "mailbox.h"
  25. #include "state.h"
  26. #include "parse.h"
  27.  
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <errno.h>
  32. #include <ctype.h>
  33. #include <sys/stat.h>
  34. #include <signal.h>
  35.  
  36. #define DISPOSITION(X) X==DISPATTACH?"attachment":"inline"
  37.  
  38. extern char *tspecials;
  39.  
  40. char B64Chars[64] = {
  41.   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  42.   'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
  43.   'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
  44.   't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
  45.   '8', '9', '+', '/'
  46. };
  47.  
  48. static void transform_to_7bit (BODY *a, FILE *fpin);
  49.  
  50. static void encode_quoted (FILE * fin, FILE *fout, int istext)
  51. {
  52.   int c, linelen = 0;
  53.   char line[77], savechar;
  54.  
  55.   while ((c = fgetc (fin)) != EOF)
  56.   {
  57.     /* Escape lines that begin with "the message separator". */
  58.     if (linelen == 5 && !strncmp ("From ", line, 5))
  59.     {
  60.       strfcpy (line, "=46rom ", sizeof (line));
  61.       linelen = 7;
  62.     }
  63.     else if (linelen == 1 && line[0] == '.')
  64.     {
  65.       strfcpy (line, "=2E", sizeof (line));
  66.       linelen = 3;
  67.     }
  68.  
  69.     /* Wrap the line if needed. */
  70.     if (linelen == 76 && ((istext && c != '\n') || !istext))
  71.     {
  72.       /* If the last character is "quoted", then be sure to move all three
  73.        * characters to the next line.  Otherwise, just move the last
  74.        * character...
  75.        */
  76.       if (line[linelen-3] == '=')
  77.       {
  78.         line[linelen-3] = 0;
  79.         fputs (line, fout);      
  80.         fputs ("=\n", fout);
  81.         line[linelen] = 0;
  82.         line[0] = '=';
  83.         line[1] = line[linelen-2];
  84.         line[2] = line[linelen-1];
  85.         linelen = 3;
  86.       }
  87.       else
  88.       {
  89.         savechar = line[linelen-1];
  90.         line[linelen-1] = '=';
  91.         line[linelen] = 0;
  92.         fputs (line, fout);
  93.         fputc ('\n', fout);
  94.         line[0] = savechar;
  95.         linelen = 1;
  96.       }
  97.     }
  98.  
  99.     if (c == '\n' && istext)
  100.     {
  101.       /* Check to make sure there is no trailing space on this line. */
  102.       if (line[linelen-1] == ' ' || line[linelen-1] == '\t')
  103.       {
  104.         if (linelen < 74)
  105.     {
  106.           sprintf (line+linelen-1, "=%2.2X", line[linelen-1]);
  107.           fputs (line, fout);
  108.         }
  109.         else
  110.     {
  111.           int savechar = line[linelen-1];
  112.  
  113.           line[linelen-1] = '=';
  114.           line[linelen] = 0;
  115.           fputs (line, fout);
  116.           fprintf (fout, "\n=%2.2X", savechar);
  117.         }
  118.       }
  119.       else
  120.       {
  121.         line[linelen] = 0;
  122.         fputs (line, fout);
  123.       }
  124.       fputc ('\n', fout);
  125.       linelen = 0;
  126.     }
  127.     else if (c != 9 && (c < 32 || c > 126 || c == '='))
  128.     {
  129.       /* Check to make sure there is enough room for the quoted character.
  130.        * If not, wrap to the next line.
  131.        */
  132.       if (linelen > 73)
  133.       {
  134.         line[linelen++] = '=';
  135.         line[linelen] = 0;
  136.         fputs (line, fout);
  137.         fputc ('\n', fout);
  138.         linelen = 0;
  139.       }
  140.       sprintf (line+linelen,"=%2.2X", c);
  141.       linelen += 3;
  142.     }
  143.     else
  144.     {
  145.       /* Don't worry about wrapping the line here.  That will happen during
  146.        * the next iteration when I'll also know what the next character is.
  147.        */
  148.       line[linelen++] = c;
  149.     }
  150.   }
  151.  
  152.   /* Take care of anything left in the buffer */
  153.   if (linelen > 0)
  154.   {
  155.     if (line[linelen-1] == ' ' || line[linelen-1] == '\t')
  156.     {
  157.       /* take care of trailing whitespace */
  158.       if (linelen < 74)
  159.         sprintf (line+linelen-1, "=%2.2X", line[linelen-1]);
  160.       else
  161.       {
  162.         savechar = line[linelen-1];
  163.         line[linelen-1] = '=';
  164.         line[linelen] = 0;
  165.         fputs (line, fout);
  166.         fputc ('\n', fout);
  167.         sprintf (line, "=%2.2X", savechar);
  168.       }
  169.     }
  170.     else
  171.       line[linelen] = 0;
  172.     fputs (line, fout);
  173.   }
  174. }
  175.  
  176. static void encode_base64 (FILE * fin, FILE *fout, int istext)
  177. {
  178.   int c1, c2, c3, ch;
  179.   int insert_newline = 0;
  180.   int linelen = 0;
  181.  
  182.   FOREVER
  183.   {
  184.     if (istext)
  185.     {
  186.       if (insert_newline)
  187.       {
  188.         c1 = '\n';
  189.         insert_newline = 0;
  190.   
  191.         c2 = fgetc(fin);
  192.         if (c2 == '\n')
  193.     {
  194.           c2 = '\r';
  195.           c3 = '\n';
  196.         }
  197.         else
  198.     {
  199.           c3 = fgetc(fin);
  200.           if (c3 == '\n')
  201.       {
  202.             c3 = '\r';
  203.             insert_newline = 1;
  204.           }
  205.         }
  206.       }
  207.       else
  208.       {
  209.         c1 = fgetc(fin);
  210.         if (c1 == '\n')
  211.     {
  212.           c1 = '\r';
  213.           c2 = '\n';
  214.           c3 = fgetc(fin);
  215.           if (c3 == '\n')
  216.       {
  217.             c3 = '\r';
  218.             insert_newline = 1;
  219.           }
  220.         }
  221.         else
  222.     {
  223.           c2 = fgetc(fin);
  224.           if (c2 == '\n')
  225.       {
  226.             c2 = '\r';
  227.             c3 = '\n';
  228.           }
  229.           else
  230.       {
  231.             c3 = fgetc(fin);
  232.             if (c3 == '\n')
  233.         {
  234.               c3 = '\r';
  235.               insert_newline = 1;
  236.             }
  237.           }
  238.         }
  239.       }
  240.     }
  241.     else /* !istext */
  242.     {
  243.       if ((c1 = fgetc(fin)) == EOF)
  244.         break;
  245.       c2 = fgetc(fin);
  246.       c3 = fgetc(fin);
  247.     }
  248.  
  249.     if (linelen + 4 >= 76)
  250.     {
  251.       fputc('\n', fout);
  252.       linelen = 0;
  253.     }
  254.  
  255.     ch = c1 >> 2;
  256.     fputc (B64Chars[ch], fout);
  257.  
  258.     if (c2 != EOF)
  259.     {
  260.       ch = ((c1 & 0x3) << 4) | (c2 >> 4);
  261.       fputc (B64Chars[ch], fout);
  262.     }
  263.     else
  264.     {
  265.       ch = (c1 & 0x3) << 4;
  266.       fputc (B64Chars[ch], fout);
  267.       fputs("==", fout);
  268.       break;
  269.     }
  270.  
  271.     if (c3 != EOF)
  272.     {
  273.       ch = ((c2 & 0xf) << 2) | (c3 >> 6);
  274.       fputc (B64Chars[ch], fout);
  275.     }
  276.     else
  277.     {
  278.       ch = (c2 & 0xf) << 2;
  279.       fputc(B64Chars[ch], fout);
  280.       fputc('=', fout);
  281.       break;
  282.     }
  283.  
  284.     ch = c3 & 0x3f;
  285.     fputc(B64Chars[ch], fout);
  286.  
  287.     linelen += 4;
  288.   }
  289.  
  290.   fputc('\n', fout);
  291. }
  292.  
  293. int mutt_write_mime_header (BODY *a, FILE *f)
  294. {
  295.   PARAMETER *p;
  296.   char buffer[STRING];
  297.   char *t;
  298.   int len;
  299.   int tmplen;
  300.  
  301.   fprintf (f, "Content-Type: %s/%s", TYPE (a->type), a->subtype);
  302.  
  303.   if (a->parameter)
  304.   {
  305.     len = 25 + strlen (a->subtype); /* approximate len. of content-type */
  306.  
  307.     p = a->parameter;
  308.     while (p)
  309.     {
  310.       fputc (';', f);
  311.  
  312.       buffer[0] = 0;
  313.       rfc822_cat (buffer, sizeof (buffer), p->value, tspecials);
  314.  
  315.       tmplen = strlen (buffer) + strlen (p->attribute) + 1;
  316.  
  317.       if (len + tmplen + 2 > 76)
  318.       {
  319.     fputs ("\n\t", f);
  320.     len = tmplen + 8;
  321.       }
  322.       else
  323.       {
  324.     fputc (' ', f);
  325.     len += tmplen + 1;
  326.       }
  327.  
  328.       fprintf (f, "%s=%s", p->attribute, buffer);
  329.  
  330.       p = p->next;
  331.     }
  332.   }
  333.  
  334.   fputc ('\n', f);
  335.  
  336.   if (a->encoding != ENC7BIT)
  337.     fprintf(f, "Content-Transfer-Encoding: %s\n", ENCODING (a->encoding));
  338.  
  339.   if (a->description)
  340.     fprintf(f, "Content-Description: %s\n", a->description);
  341.  
  342.   if (a->use_disp && (a->disposition == DISPATTACH || a->filename))
  343.   {
  344.     fprintf (f, "Content-Disposition: %s", DISPOSITION (a->disposition));
  345.     if (a->filename)
  346.     {
  347.       /* Strip off the leading path... */
  348.       if ((t = strrchr (a->filename, '/')))
  349.     t++;
  350.       else
  351.     t = a->filename;
  352.       
  353.       buffer[0] = 0;
  354.       rfc822_cat (buffer, sizeof (buffer), t, tspecials);
  355.       fprintf (f, "; filename=%s", buffer);
  356.     }
  357.  
  358.     fputc ('\n', f);
  359.   }
  360.  
  361.   /* Do NOT add the terminator here!!! */
  362.   return (ferror (f) ? -1 : 0);
  363. }
  364.  
  365. int mutt_write_mime_body (BODY *a, FILE *f)
  366. {
  367.   char boundary[SHORT_STR